﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OfficeOpenXml;

namespace TableForge
{
    #region Interfaces
    public interface IDataParser
    {
        object Parse(string value);
        string ToJson(object value);
        Type GetFieldType();
    }

    public interface ITableProcessor
    {
        void ProcessTables(List<string> tables);
        void AddParser(IDataParser parser);
        void SetClientJsonPath(string path);
        void SetClientDataClassPath(string path);
        void SetClientManagerPath(string path);
        void SetServerJsonPath(string path);
        void SetServerDataClassPath(string path);
        void SetServerManagerPath(string path);
        void SetTemplatePath(string path);
        void SetSourceDataPath(string path);
    }
    #endregion

    #region Data Structures
    public class TableMetaData
    {
        public string Name { get; set; }
        public List<TableField> Fields { get; set; } = new List<TableField>();
        public List<Dictionary<string, string>> Rows { get; set; } = new List<Dictionary<string, string>>();

        public TableField IndexField => Fields.FirstOrDefault(f => f.IsIndex);
        public List<TableField> CompositeKeyFields => Fields
            .Where(f => f.IsCompositeKey)
            .OrderBy(f => f.CompositeKeyOrder)
            .ToList();
        public bool HasCompositeKey => CompositeKeyFields.Count > 0;
        public int CompositeKeyDepth => CompositeKeyFields.Count;

        public string GenerateCompositeKeyPath(Dictionary<string, string> row)
        {
            if (!HasCompositeKey) return string.Empty;

            var pathParts = new List<string>();
            foreach (var field in CompositeKeyFields)
            {
                if (row.TryGetValue(field.Name, out string value))
                {
                    pathParts.Add(value);
                }
                else
                {
                    pathParts.Add(field.DefaultValue);
                }
            }
            return string.Join(".", pathParts);
        }
    }

    public class TableField
    {
        public string Name { get; set; }
        public string TypeName { get; set; }
        public bool IsIndex { get; set; }
        public bool IsCompositeKey { get; set; }
        public int CompositeKeyOrder { get; set; } = -1;
        public List<string> Defines { get; set; } = new List<string>();
        public int ColumnIndex { get; set; }
        public string DefaultValue { get; set; }

        public bool HasDefine(string define) => Defines.Contains(define);
    }
    #endregion

    #region Main Processor
    public class TableForgeProcessor : ITableProcessor
    {
        private readonly Dictionary<string, IDataParser> _parsers = new Dictionary<string, IDataParser>();
        private string _clientJsonPath = "./Client/Json/";
        private string _clientDataClassPath = "./Client/DataClasses/";
        private string _clientManagerPath = "./Client/Manager/";
        private string _serverJsonPath = "./Server/Json/";
        private string _serverDataClassPath = "./Server/DataClasses/";
        private string _serverManagerPath = "./Server/Manager/";
        private string _templatePath = "./Templates/";
        private string _sourceDataPath = "./DataTables/";
        private List<string> _processedTables = new List<string>();

        public void AddParser(IDataParser parser)
        {
            if (parser == null) return;
            _parsers[parser.GetType().Name] = parser;
        }

        public void SetClientJsonPath(string path) => _clientJsonPath = EnsureDirectorySeparator(path);
        public void SetClientDataClassPath(string path) => _clientDataClassPath = EnsureDirectorySeparator(path);
        public void SetClientManagerPath(string path) => _clientManagerPath = EnsureDirectorySeparator(path);
        public void SetServerJsonPath(string path) => _serverJsonPath = EnsureDirectorySeparator(path);
        public void SetServerDataClassPath(string path) => _serverDataClassPath = EnsureDirectorySeparator(path);
        public void SetServerManagerPath(string path) => _serverManagerPath = EnsureDirectorySeparator(path);
        public void SetTemplatePath(string path) => _templatePath = path;
        public void SetSourceDataPath(string path) => _sourceDataPath = path;

        public void ProcessTables(List<string> tables)
        {
            LogHeader("TableForge 处理开始");
            var stopwatch = Stopwatch.StartNew();

            try
            {
                _processedTables.Clear();
                PrepareOutputDirectories();
                ValidateTemplates();

                LogInfo("处理Excel文件...");
                ProcessExcelFiles(tables);

                LogInfo("生成配置管理器...");
                GenerateConfigManagers();

                stopwatch.Stop();
                LogSuccess($"处理完成! 共处理 {_processedTables.Count} 张表，耗时 {stopwatch.Elapsed.TotalSeconds:0.00}秒");
            }
            catch (Exception ex)
            {
                LogError($"处理失败: {ex.Message}");
                throw;
            }
        }

        #region File Processing
        private void ProcessExcelFiles(List<string> tables)
        {
            var excelFiles = GetExcelFiles();
            if (excelFiles.Count == 0)
            {
                LogWarning("未找到Excel文件");
                return;
            }

            LogInfo($"找到 {excelFiles.Count} 个Excel文件:");
            excelFiles.ForEach(f => LogInfo($"- {Path.GetFileName(f)}", 1));

            ProcessEachExcelFile(excelFiles, tables);
        }

        private List<string> GetExcelFiles()
        {
            return Directory.GetFiles(_sourceDataPath, "*.xlsx")
                .Concat(Directory.GetFiles(_sourceDataPath, "*.xlsm"))
                .Where(file => !Path.GetFileName(file).StartsWith("~$"))
                .ToList();
        }

        private void ProcessEachExcelFile(List<string> excelFiles, List<string> tables)
        {
            int processedCount = 0;
            foreach (var excelFile in excelFiles)
            {
                string fileName = Path.GetFileNameWithoutExtension(excelFile);

                if (tables.Count > 0 && !tables.Contains(fileName))
                    continue;

                processedCount++;
                ProcessSingleExcelFile(excelFile, processedCount, excelFiles.Count);
            }
        }

        private void ProcessSingleExcelFile(string excelFile, int current, int total)
        {
            LogInfo($"[{current}/{total}] 处理: {Path.GetFileName(excelFile)}");

            using (var package = new ExcelPackage(new FileInfo(excelFile)))
            {
                var worksheet = GetFirstVisibleWorksheet(package);
                if (worksheet == null)
                {
                    LogWarning("没有可见的工作表");
                    return;
                }

                ProcessWorksheet(worksheet, Path.GetFileNameWithoutExtension(excelFile));
            }
        }

        private ExcelWorksheet GetFirstVisibleWorksheet(ExcelPackage package)
        {
            return package.Workbook.Worksheets
                .FirstOrDefault(ws => ws.Hidden == eWorkSheetHidden.Visible && !ws.Name.StartsWith("$"));
        }
        #endregion

        #region Worksheet Processing
        private void ProcessWorksheet(ExcelWorksheet worksheet, string tableName)
        {
            var metaData = new TableMetaData { Name = tableName };

            // 列定义
            const int csMarkCol = 1;      // 第1列：C|S标记
            const int descCol = 2;        // 第2列：描述
            const int defineRow = 2;      // 第2行：字段定义
            const int typeRow = 3;        // 第3行：字段类型
            const int nameRow = 4;        // 第4行：字段名
            const int commentRow = 5;     // 第5行：字段备注
            const int defaultValueRow = 6; // 第6行：默认值
            const int dataStartRow = 7;   // 数据从第7行开始
            const int dataStartCol = 3;   // 数据从第3列开始

            // 读取字段定义
            ReadFieldDefinitions(worksheet, metaData, defineRow, typeRow, nameRow, defaultValueRow, dataStartCol);

            // 解析数据行
            ParseDataRows(worksheet, metaData, csMarkCol, descCol, dataStartRow, dataStartCol);

            LogInfo($"从 {metaData.Name} 加载 {metaData.Rows.Count} 行数据", 1);
            _processedTables.Add(metaData.Name);

            GenerateClientFiles(metaData);
            GenerateServerFiles(metaData);
        }

        private void ReadFieldDefinitions(ExcelWorksheet worksheet, TableMetaData metaData,
    int defineRow, int typeRow, int nameRow, int defaultValueRow, int startCol)
        {
            for (int col = startCol; col <= worksheet.Dimension.End.Column; col++)
            {
                var cellValue = worksheet.Cells[nameRow, col].Text;
                if (string.IsNullOrWhiteSpace(cellValue)) break;

                var typeCell = worksheet.Cells[typeRow, col].Text;
                string fieldType = string.IsNullOrWhiteSpace(typeCell) ? "string" : typeCell;

                // 处理复合键
                bool isCompositeKey = false;
                int compositeKeyOrder = -1;
                if (fieldType.StartsWith("key|"))
                {
                    isCompositeKey = true;
                    fieldType = fieldType.Substring(4);
                    compositeKeyOrder = metaData.Fields.Count(f => f.IsCompositeKey);
                }

                // 获取默认值
                var defaultValueCell = worksheet.Cells[defaultValueRow, col];
                string defaultValue = defaultValueCell.Text;

                if (string.IsNullOrWhiteSpace(defaultValue))
                {
                    defaultValue = GetDefaultValueByType(fieldType);
                }

                // 读取字段定义（c|s）
                var defineCell = worksheet.Cells[defineRow, col].Text;
                var defines = !string.IsNullOrWhiteSpace(defineCell)
                    ? defineCell.Split('|').Select(d => d.Trim()).ToList()
                    : new List<string>(); // 如果未输入，则置空

                // 如果字段定义为空，则不导出该字段
                if (defines.Count == 0)
                {
                    continue; // 跳过该字段
                }

                metaData.Fields.Add(new TableField
                {
                    Name = cellValue,
                    TypeName = fieldType,
                    ColumnIndex = col - 1,
                    DefaultValue = defaultValue,
                    IsCompositeKey = isCompositeKey,
                    CompositeKeyOrder = compositeKeyOrder,
                    Defines = defines // 设置字段定义
                });
            }

            // 标记索引字段
            var indexField = metaData.Fields.FirstOrDefault(f =>
                f.Name.Equals("Id", StringComparison.OrdinalIgnoreCase) ||
                f.Name.Equals("ID", StringComparison.OrdinalIgnoreCase));
            if (indexField != null)
            {
                indexField.IsIndex = true;
            }
        }

        private void ParseDataRows(ExcelWorksheet worksheet, TableMetaData metaData,
            int csMarkCol, int descCol, int dataStartRow, int dataStartCol)
        {
            for (int row = dataStartRow; row <= worksheet.Dimension.End.Row; row++)
            {
                // 处理C|S标记
                var csMark = worksheet.Cells[row, csMarkCol].Text.ToUpper();
                bool exportToClient = csMark.Contains("C");
                bool exportToServer = csMark.Contains("S");

                if (!exportToClient && !exportToServer)
                {
                    LogInfo($"跳过行 {row} (未标记导出到任何端)", 2);
                    continue;
                }

                // 读取描述
                var desc = worksheet.Cells[row, descCol].Text;
                if (!string.IsNullOrEmpty(desc))
                {
                    //LogInfo($"行 {row} 描述: {desc}", 2);
                }

                var rowData = new Dictionary<string, string>
                {
                    {"__ExportToClient", exportToClient.ToString()},
                    {"__ExportToServer", exportToServer.ToString()}
                };

                bool rowHasData = false;

                // 读取数据
                for (int col = 1; col <= metaData.Fields.Count; col++)
                {
                    var field = metaData.Fields[col - 1];
                    var cell = worksheet.Cells[row, dataStartCol + col - 1];
                    var cellValue = cell.Text;

                    if (string.IsNullOrWhiteSpace(cellValue))
                    {
                        cellValue = field.DefaultValue;
                    }

                    if (cell.Value is DateTime dateValue)
                    {
                        cellValue = dateValue.ToString("yyyy-MM-dd HH:mm:ss");
                    }

                    if (!string.IsNullOrWhiteSpace(cellValue))
                    {
                        rowHasData = true;
                    }

                    rowData[field.Name] = cellValue;
                }

                if (rowHasData)
                {
                    metaData.Rows.Add(rowData);
                }
            }
        }
        #endregion

        #region File Generation
        private void GenerateClientFiles(TableMetaData metaData)
        {
            // 读取模板文件时指定UTF-8编码
            string template = File.ReadAllText(
                Path.Combine(_templatePath, "ClientDataTableTemplate.txt"),
                Encoding.UTF8);

            string sanitizedName = SanitizeName(metaData.Name);

            // 生成字段定义
            StringBuilder fieldsBuilder = new StringBuilder();
            foreach (var field in metaData.Fields.Where(f => f.HasDefine("c")))
            {
                string cleanTypeName = field.TypeName.Replace("key|", "");
                fieldsBuilder.AppendLine($"\tpublic {cleanTypeName} {field.Name} {{ get; set; }}");
            }

            // 生成复合键注释
            StringBuilder compositeKeyBuilder = new StringBuilder();
            if (metaData.HasCompositeKey)
            {
                compositeKeyBuilder.AppendLine("\t// 复合键字段:");
                metaData.CompositeKeyFields.ForEach(f =>
                    compositeKeyBuilder.AppendLine($"\t// {f.Name} ({f.TypeName})"));
            }

            // 替换模板变量
            bool hasIndex = metaData.IndexField != null && !metaData.HasCompositeKey;
            template = template
                .Replace("$Name", sanitizedName)
                .Replace("$Fields", fieldsBuilder.ToString())
                .Replace("$HasIndex", hasIndex.ToString().ToLower())
                .Replace("$IndexType", hasIndex ? metaData.IndexField.TypeName : "int")
                .Replace("$IndexName", hasIndex ? metaData.IndexField.Name : "Id")
                .Replace("$HasCompositeKey", metaData.HasCompositeKey.ToString().ToLower())
                .Replace("$CompositeKeyFields", compositeKeyBuilder.ToString());

            // 写入类文件时指定UTF-8编码（带BOM）
            string classPath = Path.Combine(_clientDataClassPath, $"{sanitizedName}.cs");
            File.WriteAllText(classPath, template, new UTF8Encoding(true)); // true表示包含BOM
            LogSuccess($"生成客户端数据类: {Path.GetFileName(classPath)}", 1);

            // 生成JSON
            JToken json = metaData.HasCompositeKey
                ? GenerateCompositeKeyJson(metaData, "c")
                : GenerateSimpleJson(metaData, "c");

            // JSON文件也使用UTF-8编码
            string jsonPath = Path.Combine(_clientJsonPath, $"{sanitizedName}.json");
            File.WriteAllText(jsonPath, json.ToString(Formatting.Indented), new UTF8Encoding(false)); // JSON不需要BOM
            LogSuccess($"生成客户端JSON: {Path.GetFileName(jsonPath)}", 1);
        }

        private void GenerateServerFiles(TableMetaData metaData)
        {
            string template = File.ReadAllText(Path.Combine(_templatePath, "ServerDataTableTemplate.txt"));
            string sanitizedName = SanitizeName(metaData.Name);

            // 生成字段定义
            StringBuilder fieldsBuilder = new StringBuilder();
            foreach (var field in metaData.Fields.Where(f => f.HasDefine("s")))
            {
                string cleanTypeName = field.TypeName.Replace("key|", "");
                fieldsBuilder.AppendLine($"\tpublic {cleanTypeName} {field.Name} {{ get; set; }}");
            }

            // 生成复合键注释
            StringBuilder compositeKeyBuilder = new StringBuilder();
            if (metaData.HasCompositeKey)
            {
                compositeKeyBuilder.AppendLine("\t// 复合键字段:");
                metaData.CompositeKeyFields.ForEach(f =>
                    compositeKeyBuilder.AppendLine($"\t// {f.Name} ({f.TypeName})"));
            }

            // 替换模板变量
            bool hasIndex = metaData.IndexField != null && !metaData.HasCompositeKey;
            template = template
                .Replace("$Name", sanitizedName)
                .Replace("$Fields", fieldsBuilder.ToString())
                .Replace("$HasIndex", hasIndex.ToString().ToLower())
                .Replace("$IndexType", hasIndex ? metaData.IndexField.TypeName : "int")
                .Replace("$IndexName", hasIndex ? metaData.IndexField.Name : "Id")
                .Replace("$HasCompositeKey", metaData.HasCompositeKey.ToString().ToLower())
                .Replace("$CompositeKeyFields", compositeKeyBuilder.ToString());

            // 写入类文件
            string classPath = Path.Combine(_serverDataClassPath, $"{sanitizedName}.cs");
            File.WriteAllText(classPath, template);
            LogSuccess($"生成服务端数据类: {Path.GetFileName(classPath)}", 1);

            // 生成JSON
            JToken json = metaData.HasCompositeKey
                ? GenerateCompositeKeyJson(metaData, "s")
                : GenerateSimpleJson(metaData, "s");

            string jsonPath = Path.Combine(_serverJsonPath, $"{sanitizedName}.json");
            File.WriteAllText(jsonPath, json.ToString(Formatting.Indented));
            LogSuccess($"生成服务端JSON: {Path.GetFileName(jsonPath)}", 1);
        }

        private JToken GenerateCompositeKeyJson(TableMetaData metaData, string define)
        {
            JObject root = new JObject();

            foreach (var row in metaData.Rows)
            {
                if (!ShouldExport(row, define)) continue;

                JObject current = root;
                var keyPath = metaData.GenerateCompositeKeyPath(row);
                var pathParts = keyPath.Split('.');

                // 创建嵌套结构
                for (int i = 0; i < pathParts.Length - 1; i++)
                {
                    if (!current.ContainsKey(pathParts[i]))
                    {
                        current[pathParts[i]] = new JObject();
                    }
                    current = (JObject)current[pathParts[i]];
                }

                // 添加数据
                JObject dataObj = new JObject();
                foreach (var field in metaData.Fields.Where(f => f.HasDefine(define) && !f.IsCompositeKey))
                {
                    if (row.TryGetValue(field.Name, out string value) && !string.IsNullOrWhiteSpace(value))
                    {
                        dataObj[field.Name] = ParseFieldValue(field, value);
                    }
                }

                current[pathParts.Last()] = dataObj;
            }

            return root;
        }

        private JToken GenerateSimpleJson(TableMetaData metaData, string define)
        {
            JArray array = new JArray();

            foreach (var row in metaData.Rows)
            {
                if (!ShouldExport(row, define)) continue;

                JObject jsonObj = new JObject();
                foreach (var field in metaData.Fields.Where(f => f.HasDefine(define)))
                {
                    if (row.TryGetValue(field.Name, out string value) && !string.IsNullOrWhiteSpace(value))
                    {
                        jsonObj[field.Name] = ParseFieldValue(field, value);
                    }
                }

                if (jsonObj.HasValues)
                    array.Add(jsonObj);
            }

            return array;
        }

        private bool ShouldExport(Dictionary<string, string> row, string define)
        {
            return define == "c"
                ? bool.Parse(row["__ExportToClient"])
                : bool.Parse(row["__ExportToServer"]);
        }
        #endregion

        #region Utility Methods
        private string EnsureDirectorySeparator(string path)
        {
            if (string.IsNullOrEmpty(path)) return path;
            return path.EndsWith(Path.DirectorySeparatorChar.ToString())
                ? path
                : path + Path.DirectorySeparatorChar;
        }

        private string GetDefaultValueByType(string typeName)
        {
            typeName = typeName.ToLower().Trim();

            if (typeName.EndsWith("[]") || typeName.Contains("list") || typeName.Contains("array"))
                return "[]";

            switch (typeName)
            {
                case "int":
                case "int32":
                case "integer":
                case "long":
                case "int64":
                    return "0";
                case "float":
                case "single":
                case "double":
                case "decimal":
                    return "0.0";
                case "bool":
                case "boolean":
                    return "false";
                case "string":
                    return "\"\"";
                case "datetime":
                case "date":
                    return DateTime.MinValue.ToString("yyyy-MM-dd");
                case "vector2":
                    return "{x:0,y:0}";
                case "vector3":
                    return "{x:0,y:0,z:0}";
                case "color":
                    return "{r:255,g:255,b:255,a:255}";
                default:
                    if (_parsers.TryGetValue(typeName, out IDataParser parser))
                        return parser.ToJson(parser.Parse(""));
                    return "\"\"";
            }
        }

        private JToken ParseFieldValue(TableField field, string value)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(value))
                    value = field.DefaultValue;

                if (IsArrayType(field.TypeName))
                {
                    if (value == "[]") return JToken.Parse("[]");

                    // Handle string arrays specifically
                    if (field.TypeName == "string[]")
                    {
                        var items = value.Split('|').Select(s => s.Trim()).ToArray();
                        return JArray.FromObject(items);
                    }

                    // Handle other array types
                    if (field.TypeName == "int[]" || field.TypeName == "float[]")
                        return JToken.Parse($"[{value.Replace("|", ",")}]");
                }

                if (_parsers.TryGetValue(field.TypeName, out IDataParser parser))
                    return JToken.FromObject(parser.Parse(value));

                switch (field.TypeName.ToLower())
                {
                    case "int":
                    case "int32":
                    case "integer":
                        return int.Parse(value);
                    case "float":
                    case "single":
                        return float.Parse(value.Replace("f", ""));
                    case "double":
                        return double.Parse(value);
                    case "bool":
                    case "boolean":
                        return value.ToLower() == "true" || value == "1";
                    case "string":
                        return value.Trim('"');
                    case "datetime":
                    case "date":
                        return DateTime.Parse(value.Trim('"'));
                    default:
                        return value;
                }
            }
            catch (Exception ex)
            {
                LogError($"解析字段 '{field.Name}' 错误: {ex.Message}");
                return value;
            }
        }

        private bool IsArrayType(string typeName)
        {
            typeName = typeName.ToLower();
            return typeName.EndsWith("[]") || typeName.Contains("list") || typeName.Contains("array");
        }

        private string SanitizeName(string name)
        {
            return new string(name.Where(c => char.IsLetterOrDigit(c) || c == '_').ToArray());
        }
        #endregion

        #region Directory Management
        private void PrepareOutputDirectories()
        {
            LogInfo("准备输出目录...");

            PrepareDirectory(_clientJsonPath, "*.json");
            PrepareDirectory(_clientDataClassPath, "*.cs");
            PrepareDirectory(_clientManagerPath, "*.cs");

            PrepareDirectory(_serverJsonPath, "*.json");
            PrepareDirectory(_serverDataClassPath, "*.cs");
            PrepareDirectory(_serverManagerPath, "*.cs");
        }

        private void PrepareDirectory(string path, string searchPattern)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
                LogInfo($"创建目录: {path}", 1);
            }
            else
            {
                var files = Directory.GetFiles(path, searchPattern);
                if (files.Length > 0)
                {
                    LogInfo($"清理 {files.Length} 个旧 {searchPattern} 文件", 1);
                    foreach (var file in files)
                    {
                        File.Delete(file);
                    }
                }
            }
        }
        #endregion

        #region Template Management
        private void ValidateTemplates()
        {
            LogInfo("验证模板...");

            string[] requiredTemplates = {
                "ClientDataTableTemplate.txt",
                "ServerDataTableTemplate.txt",
                "ClientManagerTemplate.txt",
                "ServerManagerTemplate.txt"
            };

            bool allValid = requiredTemplates.All(t =>
                File.Exists(Path.Combine(_templatePath, t)));

            if (!allValid)
            {
                throw new FileNotFoundException("缺少必需的模板文件");
            }

            LogSuccess("所有模板验证通过", 1);
        }

        private void GenerateConfigManagers()
        {
            GenerateManager("ClientManagerTemplate.txt", _clientManagerPath, "ConfigManager.Load.cs");
            GenerateManager("ServerManagerTemplate.txt", _serverManagerPath, "ConfigManager.Load.cs");
        }

        private void GenerateManager(string templateName, string outputPath, string fileName)
        {
            string template = File.ReadAllText(Path.Combine(_templatePath, templateName));

            StringBuilder fieldsBuilder = new StringBuilder();
            StringBuilder addBuilder = new StringBuilder();

            foreach (var tableName in _processedTables)
            {
                string className = $"{SanitizeName(tableName)}_Table";
                string fieldName = SanitizeName(tableName);

                fieldsBuilder.AppendLine($"\tpublic static {className} {fieldName};");
                addBuilder.AppendLine($"\t\t{fieldName} = AddTable(new {className}());");
            }

            template = template
                .Replace("$Fields", fieldsBuilder.ToString())
                .Replace("$add", addBuilder.ToString());

            string managerPath = Path.Combine(outputPath, fileName);
            File.WriteAllText(managerPath, template);
            LogSuccess($"生成管理器: {fileName}", 1);
        }
        #endregion

        #region Logging
        private void LogInfo(string message, int indent = 0, ConsoleColor? color = null)
        {
            Console.ForegroundColor = color ?? ConsoleColor.White;
            Console.WriteLine($"{new string(' ', indent * 4)}{message}");
            Console.ResetColor();
        }

        private void LogSuccess(string message, int indent = 0)
            => LogInfo(message, indent, ConsoleColor.Green);

        private void LogWarning(string message, int indent = 0)
            => LogInfo(message, indent, ConsoleColor.Yellow);

        private void LogError(string message, int indent = 0)
            => LogInfo($"ERROR: {message}", indent, ConsoleColor.Red);

        private void LogHeader(string title)
        {
            Console.ForegroundColor = ConsoleColor.Cyan;
            string border = new string('=', title.Length + 4);
            Console.WriteLine($"\n{border}");
            Console.WriteLine($"  {title}  ");
            Console.WriteLine($"{border}\n");
            Console.ResetColor();
        }
        #endregion
    }
    #endregion

    #region Custom Parsers
    public class Vector3Parser : IDataParser
    {
        public object Parse(string value)
        {
            var parts = value.Split(',');
            return new { X = float.Parse(parts[0]), Y = float.Parse(parts[1]), Z = float.Parse(parts[2]) };
        }

        public string ToJson(object value) => JsonConvert.SerializeObject(value);
        public Type GetFieldType() => typeof(object);
    }

    public class ColorParser : IDataParser
    {
        public object Parse(string value)
        {
            var parts = value.Split(',');
            return new
            {
                R = byte.Parse(parts[0]),
                G = byte.Parse(parts[1]),
                B = byte.Parse(parts[2]),
                A = byte.Parse(parts[3])
            };
        }

        public string ToJson(object value) => JsonConvert.SerializeObject(value);
        public Type GetFieldType() => typeof(object);
    }

    public class ItemListParser : IDataParser
    {
        public object Parse(string value)
        {
            if (string.IsNullOrWhiteSpace(value) || value == "[]")
                return new List<object>();

            return value.Split('|')
                .Select(item => item.Split(','))
                .Select(parts => new
                {
                    Id = int.Parse(parts[0]),
                    Count = int.Parse(parts[1]),
                    Quality = parts.Length > 2 ? int.Parse(parts[2]) : 1
                })
                .ToList();
        }

        public string ToJson(object value) => JsonConvert.SerializeObject(value);
        public Type GetFieldType() => typeof(List<object>);
    }

    public class DateTimeParser : IDataParser
    {
        public object Parse(string value) => DateTime.Parse(value);
        public string ToJson(object value) => JsonConvert.SerializeObject(value, new JsonSerializerSettings
        {
            DateFormatString = "yyyy-MM-ddTHH:mm:ss"
        });
        public Type GetFieldType() => typeof(DateTime);
    }
    #endregion

    #region Program & Configuration
    class Program
    {
        static void Main(string[] args)
        {
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;

            var processor = new TableForgeProcessor();
            var settings = LoadSettings();

            ConfigurePaths(processor, settings);
            RegisterParsers(processor);

            try
            {
                processor.ProcessTables(new List<string>());
                PrintOutputSummary(settings);
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"处理失败: {ex.Message}");
                Console.WriteLine(ex.StackTrace);
                Console.ResetColor();
            }

            Console.WriteLine("\n按任意键退出...");
            Console.ReadKey();
        }

        static void ConfigurePaths(TableForgeProcessor processor, AppSettings settings)
        {
            processor.SetClientJsonPath(settings.Client.JsonPath);
            processor.SetClientDataClassPath(settings.Client.DataClassPath);
            processor.SetClientManagerPath(settings.Client.ManagerPath);
            processor.SetServerJsonPath(settings.Server.JsonPath);
            processor.SetServerDataClassPath(settings.Server.DataClassPath);
            processor.SetServerManagerPath(settings.Server.ManagerPath);
            processor.SetTemplatePath(settings.TemplatePath);
            processor.SetSourceDataPath(settings.SourceDataPath);
        }

        static void RegisterParsers(TableForgeProcessor processor)
        {
            processor.AddParser(new Vector3Parser());
            processor.AddParser(new ColorParser());
            processor.AddParser(new ItemListParser());
            processor.AddParser(new DateTimeParser());
        }

        static void PrintOutputSummary(AppSettings settings)
        {
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\n客户端输出:");
            Console.ResetColor();
            Console.WriteLine($"  JSON: {Path.GetFullPath(settings.Client.JsonPath)}");
            Console.WriteLine($"  数据类: {Path.GetFullPath(settings.Client.DataClassPath)}");
            Console.WriteLine($"  管理器: {Path.GetFullPath(settings.Client.ManagerPath)}");

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\n服务端输出:");
            Console.ResetColor();
            Console.WriteLine($"  JSON: {Path.GetFullPath(settings.Server.JsonPath)}");
            Console.WriteLine($"  数据类: {Path.GetFullPath(settings.Server.DataClassPath)}");
            Console.WriteLine($"  管理器: {Path.GetFullPath(settings.Server.ManagerPath)}");
        }

        static AppSettings LoadSettings()
        {
            try
            {
                if (File.Exists("appsettings.json"))
                {
                    return JsonConvert.DeserializeObject<AppSettings>(File.ReadAllText("appsettings.json"));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"加载配置错误: {ex.Message}");
            }

            return new AppSettings
            {
                SourceDataPath = "./DataTables/",
                TemplatePath = "./Templates/",
                Client = new ClientPaths
                {
                    JsonPath = "./Client/Json/",
                    DataClassPath = "./Client/DataClasses/",
                    ManagerPath = "./Client/Manager/"
                },
                Server = new ServerPaths
                {
                    JsonPath = "./Server/Json/",
                    DataClassPath = "./Server/DataClasses/",
                    ManagerPath = "./Server/Manager/"
                }
            };
        }
    }

    public class AppSettings
    {
        public string SourceDataPath { get; set; }
        public string TemplatePath { get; set; }
        public ClientPaths Client { get; set; }
        public ServerPaths Server { get; set; }
    }

    public class ClientPaths
    {
        public string JsonPath { get; set; }
        public string DataClassPath { get; set; }
        public string ManagerPath { get; set; }
    }

    public class ServerPaths
    {
        public string JsonPath { get; set; }
        public string DataClassPath { get; set; }
        public string ManagerPath { get; set; }
    }
    #endregion
}